<script setup lang="ts">
import { onMounted, ref, watch } from 'vue';

import { ElTree } from 'element-plus';

import { filterHalfCheckedParentNodes, handleTree } from '../../utils/tree';

interface ITreeProps {
  api: Function; // 获取树形数据接口
  params: {}; // 获取树形数据接口参数
  checkStrictly?: boolean;
  defaultProps: Record<string, any>;
  showCheckbox?: boolean;
  multiple?: boolean;
  nodeKey?: string;
  expandOnClickNode?: boolean;
  checkedKeys?: number[]; // 已勾选的节点ID数组，用于回显
  idField?: string; // ID字段名，默认为 'id'
  pidField?: string; // 父ID字段名，默认为 'parentId'
  childrenField?: string; // 子节点字段名，默认为 'children'
  requiredParams?: string[]; // 必需参数字段名数组，如果这些参数无效则不调用API
}
const props = defineProps<ITreeProps>();
const emit = defineEmits(['init', 'update:modelValue']);
const treeData = ref<Record<string, unknown>[]>([]);
const treeRef = ref<InstanceType<typeof ElTree> | null>(null);
const selectValue = ref<null | number | number[]>();

// 监听勾选变化
const onCheckChange = () => {
  if (treeRef.value) {
    const checkedKeys = treeRef.value.getCheckedKeys() as number[];
    // 当 checkStrictly 为 true，忽略半选节点
    const newValue = props.checkStrictly
      ? checkedKeys
      : [...checkedKeys, ...(treeRef.value.getHalfCheckedKeys() as number[])];

    selectValue.value = props.multiple ? newValue : (newValue[0] ?? null);
  }
};

// 点击节点事件处理（若需要）
const onNodeClick = (node: any) => {
  const nodeKey = props.nodeKey ?? 'id';
  const value = node[nodeKey];
  if (value === undefined) return;

  if (props.showCheckbox) {
    // 如果显示复选框，点击节点时不直接改变选中值，由复选框处理
    return;
  }
  // 非复选框模式下的处理
  selectValue.value = props.multiple ? [value] : value;
};

// 同步父组件值
watch(selectValue, (newVal) => {
  emit('update:modelValue', newVal);
});

const fetchData = async () => {
  try {
    // 检查必要参数是否有效
    if (!props.api) {
      console.warn('Tree component: api function is required');
      return;
    }
    // 检查必需参数是否有效（通用参数验证）
    if (props.requiredParams && props.requiredParams.length > 0) {
      const hasInvalidRequiredParam = props.requiredParams.some((param) => {
        const value = (props.params as any)?.[param];
        return value === undefined || value === null || value === '';
      });

      if (hasInvalidRequiredParam) {
        // 必需参数无效时，清空树数据，避免调用API
        treeData.value = [];
        return;
      }
    }
    const res = await props.api(props.params);
    const flatData = res || [];

    // 将扁平数组转换为树形结构
    treeData.value = handleTree(
      flatData,
      props.idField ?? 'id',
      props.pidField ?? 'parentId',
      props.childrenField ?? 'children',
    );
    // 处理回显数据
    if (props.checkedKeys && props.checkedKeys.length > 0) {
      const filteredKeys = filterHalfCheckedParentNodes(
        treeData.value,
        props.checkedKeys,
        {
          childrenField: props.childrenField ?? 'children',
          idField: props.idField ?? 'id',
        },
      );
      treeRef.value?.setCheckedKeys(filteredKeys);
    }
  } catch (error) {
    console.error('Error fetching data:', error);
    treeData.value = [];
  }
};

// 标记组件是否已初始化
const initialized = ref(false);

// 监听参数变化，重新获取数据
watch(
  () => [props.params, props.api],
  (newVal, oldVal) => {
    if (
      initialized.value &&
      oldVal &&
      (JSON.stringify(oldVal[0]) !== JSON.stringify(newVal[0]) ||
        oldVal[1] !== newVal[1])
    ) {
      fetchData();
    }
  },
  { deep: true },
);

onMounted(async () => {
  // 初始化设置默认选中
  // await fetchData();
  initialized.value = true;
});
</script>

<template>
  <div class="w-full">
    <ElTree
      ref="treeRef"
      :data="treeData"
      :check-strictly="props.checkStrictly"
      :expand-on-click-node="props.expandOnClickNode"
      :highlight-current="true"
      :multiple="props.multiple"
      :node-key="props.nodeKey"
      :props="props.defaultProps"
      :show-checkbox="props.showCheckbox"
      @check-change="onCheckChange"
      @node-click="onNodeClick"
    />
  </div>
</template>
